package cn.promonkey.api.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import cn.promonkey.core.base.Constants;
import cn.promonkey.core.dto.UserDto;
import cn.promonkey.core.response.ResultMsg;
import cn.promonkey.core.security.SecurityService;
import cn.promonkey.core.toolkit.HttpClientUtils;
import cn.promonkey.core.toolkit.QueryGenerator;
import cn.promonkey.core.toolkit.UserInfoUtils;
import cn.promonkey.core.utils.MD5Utils;
import cn.promonkey.core.utils.RedisUtils;
import cn.promonkey.sso.entity.LoginUser;
import jakarta.servlet.http.HttpServletRequest;
import cn.promonkey.api.common.entity.CommonTreeDto;
import cn.promonkey.api.group.entity.Group;
import cn.promonkey.api.relation.entity.Relation;
import cn.promonkey.api.relation.service.RelationService;
import cn.promonkey.api.system.entity.System;
import cn.promonkey.api.system.entity.SystemDto;
import cn.promonkey.api.user.entity.User;
import cn.promonkey.api.user.service.UserService;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;


/** @author <no value> */
@Slf4j
@RestController
@RequestMapping("/user/")
public class UserController {
  final UserService userService;
  
  final RelationService relationService;
  
  final RedisUtils redisUtils;

  public UserController(UserService userService,RelationService relationService,RedisUtils redisUtils) {
    this.userService = userService;
    this.relationService = relationService;
    this.redisUtils = redisUtils;
  }

  @RequestMapping("getPage")
  public String getPage(
      User user,
      @RequestParam(name = "page", defaultValue = "1") Integer page,
      @RequestParam(name = "size", defaultValue = "10") Integer size,
      HttpServletRequest request) {
    QueryWrapper<User> queryWrapper = QueryGenerator.initQueryWrapper(user, request.getParameterMap());
    Page<User> pageable = new Page<>(page, size);
    IPage<User> pageList = userService.page(pageable, queryWrapper);
    return ResultMsg.success(pageList);
  }

  @RequestMapping(value = "save", method = RequestMethod.POST)
  public String save(@RequestBody User user) {
	  
	  UserDto userDto = UserInfoUtils.getUserInfo();
	  user.setBusinessId(userDto.getBusinessId());
	  //校验用户信息
	  QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
	  queryWrapper.eq("user_name", user.getUserName()).eq("business_id", user.getBusinessId());
	  long size = userService.count(queryWrapper);
	  if(size>0) {
		  return ResultMsg.fail("登录名已存在，请重新输入！");
	  }
	  queryWrapper = new QueryWrapper<User>();
	  queryWrapper.or().eq("email", user.getEmail()).eq("business_id", user.getBusinessId());
	  size = userService.count(queryWrapper);
	  if(size>0) {
		  return ResultMsg.fail("邮箱已存在，请重新输入！");
	  }
	  queryWrapper = new QueryWrapper<User>();
	  queryWrapper.or().eq("phone", user.getPhone()).eq("business_id", user.getBusinessId());
	  size = userService.count(queryWrapper);
	  if(size>0) {
		  return ResultMsg.fail("电话已存在，请重新输入！");
	  }
	  // 生成一个16位的随机数
	  Random random = new Random();
	  StringBuilder sBuilder = new StringBuilder(16);
	  sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
	  int len = sBuilder.length();
	  if (len < 16) {
		  for (int i = 0; i < 16 - len; i++) {
			  sBuilder.append("0");
		  }
	  }
	  // 生成最终的加密盐
	  String salt = sBuilder.toString();
	  user.setSalt(salt);
	  user.setPassword(MD5Utils.md5AndSha(user.getPassword()+ user.getSalt()));
	  user.setStatus(0);
	  return ResultMsg.success(userService.save(user));
  }

  @RequestMapping(value = "edit", method = RequestMethod.POST)
  public String edit(@RequestBody User user) {
    return ResultMsg.success(userService.updateById(user));
  }

  @RequestMapping(value = "get")
  public String get(@RequestParam(name = "id") Long id) {
    return ResultMsg.success(userService.getById(id));
  }

  @RequestMapping(value = "enable", method = RequestMethod.POST)
  public String enable(@RequestBody Long id) {
	  User user = new User();
	  user.setUserId(id);
	  user.setStatus(0);
    return ResultMsg.success(userService.updateById(user));
  }
  
  @RequestMapping(value = "disable", method = RequestMethod.POST)
  public String disable(@RequestBody Long id) {
	  User user = new User();
	  user.setUserId(id);
	  user.setStatus(1);
    return ResultMsg.success(userService.updateById(user));
  }
  
  @RequestMapping(value = "delete", method = RequestMethod.POST)
  public String delete(@RequestBody Long id) {
    return ResultMsg.success(userService.removeById(id));
  }
  
  @RequestMapping(value = "changePassword", method = RequestMethod.POST)
  public String changePassword(@RequestBody User sysuser) {
	  User user = userService.getById(sysuser.getUserId());
	  QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
	  queryWrapper.eq("password", MD5Utils.md5AndSha(sysuser.getPassword()+user.getSalt())).eq("user_id", sysuser.getUserId());
	  long count = userService.count(queryWrapper);
	  if( count == 0 ) {
		 return ResultMsg.fail("用户名或密码错误！");
	  }
	  // 生成一个16位的随机数
	  Random random = new Random();
	  StringBuilder sBuilder = new StringBuilder(16);
	  sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
	  int len = sBuilder.length();
	  if (len < 16) {
		  for (int i = 0; i < 16 - len; i++) {
			  sBuilder.append("0");
		  }
	  }
	  // 生成最终的加密盐
	  String salt = sBuilder.toString();
	  String newPw = sysuser.getUserName();
	  sysuser.setUserName(null);
	  sysuser.setSalt(salt);
	  sysuser.setPassword(MD5Utils.md5AndSha(newPw + salt));
    return ResultMsg.success(userService.updateById(sysuser));
  }
  
  @RequestMapping(value = "resetPassword", method = RequestMethod.POST)
  public String resetPassword(@RequestBody User sysuser,HttpServletRequest request) {
	  //获取当前用户权限，不足的返回异常
	  String accessToken = request.getHeader("Authorization");
	  Object uid = redisUtils.hget(Constants.ACCESS_TOKEN_HASH, accessToken);
	  //Object refreshToken = redisUtils.hget(Constants.REFRESH_TOKEN_HASH, loginUser.getRefresh_token());
	  if(uid!=null) {
		  User user = userService.getById((int)uid+0l);
		  //不是管理员
		  if(user.getType()!=1 || user.getBusinessId()!=sysuser.getBusinessId()) {
			  return ResultMsg.fail(413, "您无权进行重置密码操作");
		  }
	  }else {
		  return ResultMsg.fail(401, "登录超时");
	  }
	  
	  
	  QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
	  queryWrapper.eq("user_id", sysuser.getUserId());
	  long count = userService.count(queryWrapper);
	  if( count == 0 ) {
		 return ResultMsg.fail("无效的重置请求！");
	  }
	  // 生成一个16位的随机数
	  Random random = new Random();
	  StringBuilder sBuilder = new StringBuilder(16);
	  sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
	  int len = sBuilder.length();
	  if (len < 16) {
		  for (int i = 0; i < 16 - len; i++) {
			  sBuilder.append("0");
		  }
	  }
	  // 生成最终的加密盐
	  String salt = sBuilder.toString();
	  String newPw = sysuser.getUserName();
	  sysuser.setSalt(salt);
	  sysuser.setUserName(null);
	  sysuser.setPassword(MD5Utils.md5AndSha(newPw + salt));
    return ResultMsg.success(userService.updateById(sysuser));
  }
  
  @RequestMapping(value = "getUser", method = RequestMethod.POST)
  public String getUser(@RequestBody Long id) {
	  
	  UserDto user = UserInfoUtils.getUserInfo();
	  CommonTreeDto dto = new CommonTreeDto();
	  QueryWrapper<User> userWrapper = new  QueryWrapper<>();
	  userWrapper.eq("business_id", user.getBusinessId());
	  List<User> userList = userService.list(userWrapper);
	  dto.setUser(userList);
	  QueryWrapper<Relation> queryWrapper = new  QueryWrapper<>();
	  queryWrapper.eq("group_id", id);
	  List<Relation> relationList = relationService.list(queryWrapper);
	  dto.setCheck(relationList.stream().map(Relation::getUserId).collect(Collectors.toList()));
	  
    return ResultMsg.success(dto);
  }
  
	@RequestMapping(value = "getUserId", method = RequestMethod.POST)
	public String getUserId(@RequestBody LoginUser loginuser,
		      HttpServletRequest request) {
		String userName= loginuser.getJson();
		UserDto userDto = UserInfoUtils.getUserInfo();
		QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
		if(loginuser.getUserId()!=null) {
			queryWrapper.eq("user_id", loginuser.getUserId()).eq("business_id", userDto.getBusinessId());
		}else {
			queryWrapper.or().eq("name", userName).eq("business_id", userDto.getBusinessId());
			queryWrapper.or().eq("phone", userName).eq("business_id", userDto.getBusinessId());
			queryWrapper.or().eq("email", userName).eq("business_id", userDto.getBusinessId());
		}
		
		List<User> userList = userService.list(queryWrapper);
		if(userList.size()>0) {
			User user = userList.get(0);
			
			user.setPassword(null);
			user.setSalt(null);
			
			return  ResultMsg.success(user);
		}else {
			return ResultMsg.success();
		}
	}
	
	@RequestMapping(value = "getUsers", method = RequestMethod.POST)
	public String getUsers() {
		//
		//QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
		//queryWrapper.isNotNull("phone");
		//queryWrapper.eq("business_id", userDto.getBusinessId());
		//List<User> userList = userService.list(queryWrapper);
		
		UserDto userDto = UserInfoUtils.getUserInfo();
		List<User> userList = (List<User>)redisUtils.hget("USER_ID_LIST", userDto.getBusinessId().toString());
		
		for(User user:userList) {
			user.setPassword(null);
			user.setSalt(null);
		}
		return ResultMsg.success(userList);
	}
	
	@RequestMapping("upload")
	  public String upload(MultipartFile file,HttpServletRequest httpServletRequest) throws SocketException, IOException {
			
		UserDto userDto = UserInfoUtils.getUserInfo();
		List<User> userList = new ArrayList<>();
		List<User> updList = new ArrayList<>();

		Workbook workbook = new XSSFWorkbook(file.getInputStream());
		// 如果excel的后缀是xls,说明是03版，需要用如下方法
		// Workbook workbook = new HSSFWorkbook(is);
		//读取工作簿的第一张表格
		Sheet sheet = workbook.getSheetAt(0);
		  
		for (int i = sheet.getFirstRowNum() + 1; i <= sheet.getLastRowNum(); i++) {
			Row row = sheet.getRow(i);
			User temp = new User();
			
			temp.setPhone(getCellValue(row.getCell(2)));

			temp.setUserName(getCellValue(row.getCell(0)));
			temp.setName(getCellValue(row.getCell(1)));

			temp.setEmail(getCellValue(row.getCell(3)));
			
			temp.setPassword(getCellValue(row.getCell(4)));
			
			// 生成一个16位的随机数
			Random random = new Random();
			StringBuilder sBuilder = new StringBuilder(16);
			sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
			int len = sBuilder.length();
			if (len < 16) {
				for (int j = 0; j < 16 - len; j++) {
					sBuilder.append("0");
				}
			}
			// 生成最终的加密盐
			String salt = sBuilder.toString();
			temp.setSalt(salt);
			temp.setPassword(MD5Utils.md5AndSha(MD5Utils.getSHA256Str(temp.getPassword())+ temp.getSalt()));
	
		  	temp.setType("普通用户".equals(getCellValue(row.getCell(5)))?0:1);
		  	temp.setStatus(0);
		  	temp.setBusinessId(userDto.getBusinessId());
		  	QueryWrapper<User> userWrapper = new QueryWrapper<>();
		  	userWrapper.eq("phone", temp.getPhone());
		  	List<User> list = userService.list(userWrapper);
		  	if(list.size()>0) {
		  		User t = list.get(0);
		  		t.setName(temp.getName());
		  		t.setEmail(temp.getEmail());
		  		updList.add(t);
	  		
		  	}else {
		  		userList.add(temp);
		  	}
		  }
				
		  if(userList.size()>0) {
			  userService.saveBatch(userList);
		  }
		  if(updList.size()>0) {
			  userService.updateBatchById(updList);
		  }
	  
		  return ResultMsg.success();
	  }

		private String getCellValue(Cell cell) {
			if (cell == null) {
				return "";
			}
			if ("NUMERIC".equals(cell.getCellType().name())) {
				return new BigDecimal(cell.getNumericCellValue()).toString();
			} else if ("STRING".equals(cell.getCellType().name()))
				return StringUtils.trimToEmpty(cell.getStringCellValue());
			else if ("FORMULA".equals(cell.getCellType().name())) {
				return StringUtils.trimToEmpty(cell.getCellFormula());
			} else if ("BLANK".equals(cell.getCellType().name())) {
				return "";
			} else if ("BOOLEAN".equals(cell.getCellType().name())) {
				return String.valueOf(cell.getBooleanCellValue());
			} else if ("ERROR".equals(cell.getCellType().name())) {
				return "ERROR";
			} else {
				return cell.toString().trim();
			}
		}
  
}
